package design;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class leetCode1242 {

    private ConcurrentHashMap<String,String> visited = new ConcurrentHashMap<>();

    private final LinkedBlockingQueue<String> wait_process_urls = new LinkedBlockingQueue<String>();
    private String domain = null;
    private AtomicInteger future_task_num = new AtomicInteger(0);

    public List<String> crawl(String startUrl, HtmlParser htmlParser) {
        if(startUrl == null || htmlParser == null) return new ArrayList<>();

        domain = decodeUrl(startUrl);

        wait_process_urls.add(startUrl);
        while (future_task_num.get() > 0 || wait_process_urls.size() > 0){
            String url = null;
            try {
               url =  wait_process_urls.poll(1000, TimeUnit.MICROSECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(url == null){
                continue;
            }
            visited.put(url,url);
            String finalUrl = url;

            AtomicInteger task_rum = future_task_num;
            future_task_num.incrementAndGet();
            new Thread(() -> {
                try {
                    List<String> lst = htmlParser.getUrls(finalUrl);
                    if(!lst.isEmpty()){
                        for (String s : lst) {
                            if(!visited.containsKey(s) && domain.equals(decodeUrl(s))){
                                wait_process_urls.add(s);
                            }
                        }


                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
                task_rum.decrementAndGet();
            }).start();
        }
        return new ArrayList<>(visited.keySet());
    }

    public String decodeUrl(String startUrl){
        if(startUrl == null) return null;
        int end = startUrl.indexOf("/", 7);
        if(end == -1){
            end = startUrl.length();
        }
        return startUrl.substring(7,end);
    }

    interface HtmlParser {
        // Return a list of all urls from a webpage of given url.
        // This is a blocking call, that means it will do HTTP request and return when this request is finished.
        public List<String> getUrls(String url);
    }
}
